<?php
/**
 * This file is part of Hyperf Mall.
 *
 * @link     https://gitee.com/scwlkj/hyperf_mall
 * @contact  hyperf_mall@163.com
 */

namespace App\Repository;


use App\Exception\BaseException;
use App\Model\BaseSpecModel;
use App\Model\BaseSpecValueModel;
use App\Utils\DB;
use Hyperf\Di\Annotation\Inject;
use PHPUnit\Exception;


class BaseSpecRepository extends BaseRepository
{
    /**
     * @Inject
     * @var BaseSpecModel
     */
    protected $model;

    public function getPageRows(array $conditions = [], array $fields = ['*'], int $page = 1, int $size = 10): array
    {
        $count = $this->_searchFactor($conditions)->count();

        $offset = max(0, ($page-1)*$size);
        $res = $this->_searchFactor($conditions)->offset($offset)->limit($size)->get($fields)->toArray();

        $spec_ids = array_column($res, 'id');
        $spec = BaseSpecValueRepository::getInstance()->getRows(['spec_id'=>$spec_ids],['id','spec_id','title']);

        foreach ($res as &$val){
            $attr_name = collect($spec)->where('spec_id',$val['id'])->all();
            $val['spec_name'] = implode(',', array_column($attr_name,'title'));
        }

        return ['total'=>$count, 'data'=>$res];
    }

    /**
     * Notes: 添加基础规格
     * @param array $data
     * @return bool
     * @throws BaseException
     */
    public function createSpec(array $data)
    {
        $spec_name = $data['spec_name'];
        unset($data['spec_name']);

        DB::beginTransaction();
        try{
            $spec_model = $this->baseAdd($data);
            $spec_id = $spec_model['id'];

            $spec_value = [];
            array_map(function ($val) use (&$spec_value, $spec_id){
                $spec_value[] = [
                    'title'         =>$val['value'],
                    'sort'          =>$val['sort'],
                    'spec_id'       =>$spec_id,
                    'saas_id'       =>get_saas_id(),
                    'create_time'   =>time(),
                    'update_time'   =>time(),
                ];
            }, $spec_name);
            BaseSpecValueModel::getInstance()->insert($spec_value);
            DB::commit();

            return true;
        }catch (Exception $exception){
            DB::rollBack();
            throw new BaseException(BaseException::BASE_ERROR, $exception->getMessage());
        }
    }

    /**
     * Notes: 重写 detail
     * @param int $id
     * @return array
     */
    public function detailSpec(int $id): array
    {
        $spec = $this->getOne(['id'=>$id]);
        $spec['spec_value'] = BaseSpecValueRepository::getInstance()->getRows(['spec_id'=>$id],['title','sort','id']);

        return $spec;
    }

    public function updateSpec($id, $data)
    {
        $spec_name = $data['spec_name'];
        unset($data['spec_name']);
        DB::beginTransaction();
        try{
            $this->updateByConditions(['id'=>$id], $data);

            $spec_value = [];
            array_map(function ($val) use (&$spec_value, $id){
                if($val['id']){
                    $_data = [
                        'title'         =>$val['value'],
                        'sort'          =>$val['sort'],
                    ];
                    BaseSpecValueRepository::getInstance()->updateByConditions(['id'=>$val['id']],$_data);
                }else{
                    $spec_value[] = [
                        'title'         =>$val['value'],
                        'sort'          =>$val['sort'],
                        'spec_id'       =>$id,
                        'saas_id'       =>get_saas_id(),
                        'create_time'   =>time(),
                        'update_time'   =>time(),
                    ];
                }
            }, $spec_name);

            BaseSpecValueModel::getInstance()
                ->where('spec_id', $id)
                ->whereNotIn('id', array_column($spec_name, 'id'))
                ->delete();

            if(count($spec_value)) BaseSpecValueModel::getInstance()->insert($spec_value);

            DB::commit();
            return true;
        }catch (Exception $exception){
            DB::rollBack();
            throw new BaseException(BaseException::BASE_ERROR, $exception->getMessage());
        }
    }

    public function deleteSpec(int $id)
    {
        DB::beginTransaction();
        try{
            $this->baseRemove($id);
            BaseSpecValueModel::getInstance()
                ->where('spec_id', $id)
                ->delete();

            DB::commit();

            return true;
        }catch (Exception $exception){
            DB::rollBack();
            throw new BaseException(BaseException::BASE_ERROR, $exception->getMessage());
        }
    }
}
